//---------------------------------------------------------------------------

#include "vcl_stl.h"
#pragma hdrstop

#include "h_base.h"
#include "h_xml.h"
#include "h_global.h"
using namespace h_base;
using namespace h_xml;

#include "h_transferthread.h"
#include "t_mainform.h"
#include "h_g.h"
#include "h_i18n.h"

static const char *ProtocolVersion = "SIMJIE0104";
//---------------------------------------------------------------------------

__fastcall HTransferThread::HTransferThread(bool CreateSuspended)
   : HThread(CreateSuspended)
{
   FOverwriteEvent = new TSimpleEvent(false);
}

__fastcall HTransferThread::~HTransferThread(void)
{
   delete FOverwriteEvent;
}

void __fastcall HTransferThread::SetOverwrite(bool Overwrite)
{
   FOverwrite = Overwrite;
   FOverwriteEvent->SetEvent();
}

bool __fastcall HTransferThread::WaitForOverwriteEvent(void)
{
   int r;
   HANDLE Events[2];

   Events[0] = reinterpret_cast<HANDLE>(FExitEvent->Handle);
   Events[1] = reinterpret_cast<HANDLE>(FOverwriteEvent->Handle);

   r = WaitForMultipleObjects(2, Events, false, INFINITE);

   return r == WAIT_OBJECT_0 + 1;
}

bool __fastcall HTransferThread::GetText(vector<string> &Text)
{
   FILE *f;

   Text.clear();
   f = _wfopen(UnicodeString(UTF8String(FFullFileName.c_str())).c_str(), L"rt");

   if( f == NULL )
   {
      FResultMsg = "open file fail";
      return false;
   }

   for( ; ; )
   {
      char s[4096 + 1];
      if( h_base::ReadLine(f, s, 4096) == -1 )
         break;
      Text.push_back(s);
   }

   fclose(f);
   return true;
}

void __fastcall HTransferThread::Execute(void)
{
   const char *PVER = FProtocol <= "0103" ? "" : ProtocolVersion;

   char c;
   int r, i, Len, Step;
   SOCKET Sock = INVALID_SOCKET;
   DWORD ErrCode;
   vector<string> Text;
   HANDLE EventHandles[1];
   char TmpBuf[4096 + 1];
   UTF8String FileName = ExtractFileName(FFileName.c_str());

   EventHandles[0] = reinterpret_cast<HANDLE>(FExitEvent->Handle);

   if( !GetText(Text) )
      goto error;

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(TmpBuf, 200, h_g::I18nString("h_transferthread:CREATE_SOCKET_ERROR"),
         WSAGetLastError());
      FResultMsg = TmpBuf;
      goto error;
   }

   r = HComm::Connect(Sock, FIpAddr.c_str(), FPort, 10,
      &ErrCode, EventHandles, 1);

   if( r > 0 )
      goto cancel;

   if( r < 0 )
   {
      snprintf(TmpBuf, 200, h_g::I18nString("h_transferthread:CONNECT_ERROR"),
         r, ErrCode);
      FResultMsg = TmpBuf;
      goto error;
   }

   snprintf(TmpBuf, 4096, "%sG|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      FId.c_str(), FileName.c_str(), FPassword.c_str());

   r = HComm::WriteByLength(Sock, TmpBuf, strlen(TmpBuf),
      INFINITE, &ErrCode, EventHandles, 1);

   if( r > 0 )
      goto cancel;

   if( r < 0 )
   {
      snprintf(TmpBuf, 200, h_g::I18nString("h_transferthread:WRITE_ERROR"),
         r, ErrCode);
      FResultMsg = TmpBuf;
      goto error;
   }

   r = HComm::Read(Sock, &c, 1, INFINITE,
      &ErrCode, EventHandles, 1);

   if( r > 0 )
      goto cancel;

   if( r < 0 )
   {
      snprintf(TmpBuf, 200, h_g::I18nString("h_transferthread:READ_ERROR"),
         r, ErrCode);
      FResultMsg = TmpBuf;
      goto error;
   }

   if( c == '3' ) // password not correct
   {
      FResultMsg = h_g::I18nString("h_transferthread:PASSWORD_NOT_CORRECT");
      goto error;
   }

   if( c == '4' ) // access denied
   {
      FResultMsg = h_g::I18nString("h_transferthread:ACCESS_DENIED");
      goto error;
   }

   for( Len = 0, i = 0; i < Text.size(); i++ )
      Len += Text[i].length() + 1;

   snprintf(TmpBuf, 200, "%08x", Len);
   r = HComm::Write(Sock, TmpBuf, 8, INFINITE,
      &ErrCode, EventHandles, 1);

   if( r > 0 )
      goto cancel;

   if( r < 0 )
   {
      snprintf(TmpBuf, 200, h_g::I18nString("h_transferthread:WRITE_ERROR"),
         r, ErrCode);
      FResultMsg = TmpBuf;
      goto error;
   }

   Step = ( Text.size() + 9 ) / 10;

   for( i = 0; i < Text.size(); i++ )
   {
      if( i % Step == 0 )
      {
         PostMessage(MainForm->Handle, HM_TRANSFERPROGRESS, 0, 0);
         if( WaitForSingleObject(EventHandles[0], 30) == WAIT_OBJECT_0 )
            goto cancel;
      }
      r = HComm::Write(Sock, Text[i].c_str(), Text[i].length(), INFINITE,
         &ErrCode, EventHandles, 1);
      if( r > 0 )
         goto cancel;
      if( r < 0 )
      {
         snprintf(TmpBuf, 200, h_g::I18nString("h_transferthread:WRITE_ERROR"),
            r, ErrCode);
         FResultMsg = TmpBuf;
         goto error;
      }
      r = HComm::Write(Sock, "\n", 1, INFINITE,
         &ErrCode, EventHandles, 1);
      if( r > 0 )
         goto cancel;
      if( r < 0 )
      {
         snprintf(TmpBuf, 200, h_g::I18nString("h_transferthread:WRITE_ERROR"),
            r, ErrCode);
         FResultMsg = TmpBuf;
         goto error;
      }
   }

   r = HComm::Read(Sock, &c, 1, INFINITE,
      &ErrCode, EventHandles, 1);

   if( r > 0 )
      goto cancel;

   if( r < 0 )
   {
      snprintf(TmpBuf, 200, h_g::I18nString("h_transferthread:READ_ERROR"),
         r, ErrCode);
      FResultMsg = TmpBuf;
      goto error;
   }

   if( c == '0' ) // success
      goto end;

   if( c == '1' ) // fail
   {
      FResultMsg = h_g::I18nString("h_transferthread:SERVER_FAIL");
      goto error;
   }

end :

   closesocket(Sock);
   PostMessage(MainForm->Handle, HM_TRANSFERCOMPLETE, 0, 0);
   return;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   PostMessage(MainForm->Handle, HM_TRANSFERCOMPLETE, 0, 0);
   return;

cancel :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   PostMessage(MainForm->Handle, HM_TRANSFERCANCELED, 0, 0);
}

#pragma package(smart_init)
